﻿using System;
using System.Collections.Generic;
using System.Text;
using JWFW.SFL;
using JWFW.Encrypt;
using System.IO;
using JWFW.BOL;

namespace BaseClient
{
    public class RegHelper
    {
        /// <summary>
        /// 访问WS的代理类
        /// </summary>
        protected static IValidateReg s_VR = null;
        /// <summary>
        /// 设置WS的URL
        /// </summary>
        /// <param name="vr">WS代理</param>
        /// <param name="url">WS的url</param>
        public static void SetWSURL(IValidateReg vr, string url)
        {
            s_VR = vr;
            s_VR.Url = url;
        }

        public RegHelper(string toolCode, string versionNumber)
        {
            m_toolCode = toolCode;
            m_versionNumber = versionNumber;
            this.Init();
            this.InitTimer();
            this.Start();
        }

        private string m_sn = "";
        private System.Timers.Timer m_timer = new System.Timers.Timer();
        private int m_timerInterval = 100;
        private List<string> m_bakMC = new List<string>();
        private Random m_random = new Random((int)DateTime.Now.Ticks);
        private string m_versionNumber = "1.0";
        private bool m_registered = false;
        private bool m_expired = true;
        protected bool m_running = false;
        private string m_regFileName = "Config.dat";
        private string m_regCode = "";
        private string m_toolCode = "";
        private DateTime m_date = DateTime.MinValue;
        private string m_extensionInfo = "";

        /// <summary>
        /// 获取工具的序列号
        /// </summary>
        public string SN
        {
            get
            {
                if (m_sn == "")
                {
                    m_sn = EncryptOP.EncryptString(GetMC());
                }
                return m_sn;
            }
        }
        /// <summary>
        /// 获取是否注册有效
        /// </summary>
        public bool Registered
        {
            get { return m_registered; }
        }
        /// <summary>
        /// 获取是否过期
        /// </summary>
        public bool Expired
        {
            get { return m_expired; }
        }
        /// <summary>
        /// 获取或设置程序是否处于运行中，确定是否必须进行注册信息检查
        /// </summary>
        public bool Running
        {
            get { return m_running; }
            set { m_running = value; }
        }
        /// <summary>
        /// 获取保存注册信息的配置文件
        /// </summary>
        public string RegFileName
        {
            get { return m_regFileName; }
        }
        /// <summary>
        /// 获取注册码
        /// </summary>
        public string RegCode
        {
            get { return m_regCode; }
        }
        /// <summary>
        /// 获取工具代号
        /// </summary>
        public string ToolCode
        {
            get { return m_toolCode; }
        }
        /// <summary>
        /// 获取工具到期时间
        /// </summary>
        public DateTime Date
        {
            get { return m_date; }
        }
        /// <summary>
        /// 获取扩展信息
        /// </summary>
        public string ExtensionInfo
        {
            get { return m_extensionInfo; }
        }

        #region Timer操作

        /// <summary>
        /// Timer启动，将在运行过程中检查注册信息
        /// </summary>
        protected void Start()
        {
            if (!m_timer.Enabled)
            {
                m_timer.Start();
            }
        }
        /// <summary>
        /// 初始化Timer
        /// </summary>
        protected void InitTimer()
        {
            m_timer.Elapsed -= new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
            m_timer.Elapsed += new System.Timers.ElapsedEventHandler(m_timer_Elapsed);
            m_timer.Interval = 1000 * m_timerInterval;
        }

        protected void m_timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            this.DoTimer();
        }

        /// <summary>
        /// Timer触发后的执行，若有任何异常将会退出程序
        /// </summary>
        protected void DoTimer()
        {
            //运行时必须检查暗桩
            if (m_running)
            {
                this.SnagValidate();
            }
            else
            {
                //非运行时未注册或已过期则不检查
                if (!m_registered || m_expired)
                {
                    return;
                }
                //非运行时，注册信息是正确的，需要检查暗桩
                else
                {
                    this.SnagValidate();
                }
            }
        }

        #endregion

        #region 事件
        /// <summary>
        /// 验证扩展信息
        /// </summary>
        public delegate void ValidateExtensionInfoHandle(string extensionInfo);
        /// <summary>
        /// 验证Name失败
        /// </summary>
        public event ValidateExtensionInfoHandle OnValidateExtensionInfo;

        protected void DoValidateExtensionInfo(string extensionInfo)
        {
            if (OnValidateExtensionInfo != null)
            {
                OnValidateExtensionInfo(extensionInfo);
            }
        }

        #endregion

        /// <summary>
        /// 关闭工具
        /// </summary>
        public void Close()
        {
            System.Environment.Exit(0);
            ThrowRandomException();//若退出代码被破解，则随机抛出异常
        }
        /// <summary>
        /// 正常初始化验证信息
        /// </summary>
        public void Init()
        {
            try
            {
                lock (this)
                {
                    if (File.Exists(m_regFileName))
                    {
                        string tmp = File.ReadAllText(m_regFileName);
                        tmp = EncryptOP.DecryptString(tmp);
                        this.NormalValidate(tmp);
                    }
                }
            }
            catch
            {
                this.ResetInfo();
            }
        }
        /// <summary>
        /// 保存注册码到注册文件
        /// </summary>
        /// <param name="regCode"></param>
        public void SaveRegCode(string regCode)
        {
            lock (this)
            {
                this.NormalValidate(regCode, true);
                regCode = EncryptOP.EncryptString(regCode);
                File.WriteAllText(m_regFileName, regCode);
            }
        }
        /// <summary>
        /// 获取提交到服务器的客户端信息，其中包含机器码和注册码
        /// </summary>
        /// <param name="extensionInfo"></param>
        /// <returns></returns>
        public string GetClientInfo(string extensionInfo = "")
        {
            string res = EncryptOP.EncryptString(EncryptOP.EncryptString(GetMC2())) + CommonOP.Spliter + RegCode + CommonOP.Spliter + m_versionNumber + CommonOP.Spliter + extensionInfo;
            return EncryptOP.RandomMultiTimesEncrypt(EncryptOP.InsertRandom(res));
        }
        /// <summary>
        /// 暗桩验证
        /// </summary>
        public void SnagValidate()
        {
            if (CommonOP.RandomAction(10))
            {
                this.Init();
            }
            if (CommonOP.RandomAction(10))
            {
                VSN();
            }
            if (CommonOP.RandomAction(10))
            {
                VDT();
            }
            if (CommonOP.RandomAction(10))
            {
                VTC();
            }
            if (CommonOP.RandomAction(10))
            {
                VEI();
            }
            if (CommonOP.RandomAction(1))
            {
                try
                {
                    //todo: 连接网络
                }
                catch { }
            }
        }

        /// <summary>
        /// 创建试用帐户，返回注册码或抛异常
        /// </summary>
        /// <param name="clientInfo">提交到服务器的信息</param>
        /// <returns>注册码</returns>
        public void TrialAccount()
        {
            string res = "";
            try
            {
                res = s_VR.TrialAccount(EncryptOP.EncryptString(SN + CommonOP.Spliter + ToolCode));
                res = EncryptOP.RemoveRandomMultiRimesEncrypt(res);
                if (res.StartsWith(CommonOP.Spliter + CommonOP.Spliter))
                {
                    HandleServerError(res.Substring(2));
                }
                else if (res.StartsWith(CommonOP.Spliter))
                {
                }
                else
                {
                    this.SaveRegCode(EncryptOP.RemoveInsertRandom(EncryptOP.RemoveRandomReverse(EncryptOP.RemoveInsertRandom(EncryptOP.RemoveRandomReverse(res)))));
                }
            }
            catch (RegException ce)
            {
                throw ce;
            }
            catch
            {
                throw new RegException(Base64.Decrypt(SERVERERROR));
            }
        }

        /// <summary>
        /// 获取机器码
        /// </summary>
        /// <returns></returns> 
        public string GetMC()
        {
            string tmp = EnvironmentOP.GetHDInfo(0) + EnvironmentOP.GetMacAddress() + m_toolCode;
            tmp = MD5.GetMD5_16(EncryptOP.EncryptString(tmp)).ToUpper();
            for (int i = 0; i < tmp.Length; i++)
            {
                m_bakMC.Add(tmp[i].ToString());
            }
            return tmp;
        }
        /// <summary>
        /// 从备份的机器码中获取机器码，用于暗桩验证
        /// </summary>
        /// <returns></returns>
        public string GetMC2()
        {
            StringBuilder res = new StringBuilder(16);
            for (int i = 0; i < m_bakMC.Count; i++)
            {
                res.Append(m_bakMC[i]);
            }
            return res.ToString();
        }
        /// <summary>
        /// 获取机器码，用于暗桩验证
        /// </summary>
        /// <returns></returns>
        public string GetMC3()
        {
            string tmp = EnvironmentOP.GetHDInfo(0) + EnvironmentOP.GetMacAddress() + m_toolCode;
            tmp = MD5.GetMD5_16(EncryptOP.EncryptString(tmp)).ToUpper();
            return tmp;
        }
        /// <summary>
        /// 抛出异常
        /// </summary>
        protected void ThrowRandomException()
        {
            int r = m_random.Next(4);
            if (r == 0)
            {
                int t = 1 / int.Parse("0");
            }
            if (r == 1)
            {
                object o = null;
                Console.WriteLine(o.ToString());
            }
            if (r == 2)
            {
                int[] a = new int[1];
                Console.WriteLine(a[2]);
            }
            if (r >= 3)
            {
                System.Net.Dns.GetHostEntry("siji");
            }
        }
        /// <summary>
        /// 普通验证注册码是否有效及过期
        /// </summary>
        /// <param name="regCode"></param>
        /// <param name="throwException"></param>
        protected void NormalValidate(string regCode, bool throwException = false)
        {
            try
            {
                string[] strs = this.GetSplitInfoFromRegCode(regCode);
                if (strs.Length == 5)
                {
                    m_date = DateTime.Parse(this.GetInfoUnit(strs[3]));
                    if (strs[0] == MD5.GetMD5_8(SN))
                    {
                        m_registered = true;
                    }
                    else
                    {
                        throw new RegException(Base64.Decrypt(INVALIDREGCODE));
                    }
                    if (m_date.AddDays(1) >= this.GetComparedDT())
                    {
                        m_expired = false;
                    }
                    else
                    {
                        throw new RegException(Base64.Decrypt(EXPIREDREGCODE));
                    }
                    m_regCode = regCode;
                }
            }
            catch (RegException ex)
            {
                if (throwException)
                {
                    throw ex;
                }
            }
            catch
            {
                if (throwException)
                {
                    throw new RegException(Base64.Decrypt(INVALIDREGCODE));
                }
            }
        }
        /// <summary>
        /// 重置各信息
        /// </summary>
        protected void ResetInfo()
        {
            m_expired = true;
            m_registered = false;
            m_regCode = "";
            m_date = DateTime.MinValue;
            m_extensionInfo = "";
        }

        /// <summary>
        /// 从注册码中获取分割好的信息
        /// </summary>
        /// <param name="regCode"></param>
        /// <returns></returns>
        protected string[] GetSplitInfoFromRegCode(string regCode)
        {
            string tmp = EncryptOP.RemoveInsertRandom(EncryptOP.RemoveRandomMultiRimesEncrypt(regCode));
            string[] strs = CommonOP.SplitString(tmp, CommonOP.Spliter, false);
            return strs;
        }
        /// <summary>
        /// 获取分割后解密的信息单元
        /// </summary>
        /// <param name="encryptInfo"></param>
        /// <returns></returns>
        protected string GetInfoUnit(string encryptInfo)
        {
            return EncryptOP.RemoveInsertRandom(EncryptOP.RemoveRandomReverse(Base64.Decrypt(encryptInfo)));
        }
        /// <summary>
        /// 获取用于验证是否过期的时间
        /// </summary>
        /// <returns></returns>
        protected DateTime GetComparedDT()
        {
            DateTime dt = CommonOP.GetChineseDateTime();
            if (dt == DateTime.MinValue)
            {
                dt = DateTime.Now;
            }
            return dt;
        }
        /// <summary>
        /// 暗桩验证软件序列号
        /// </summary>
        protected void VSN()
        {
            try
            {
                string sn = EncryptOP.EncryptString(this.GetMC3());
                if (sn != m_sn)
                {
                    this.Close();
                }
                if (RegCode != "")
                {
                    string[] strs = this.GetSplitInfoFromRegCode(RegCode);
                    if (strs[0] != MD5.GetMD5_8(sn))
                    {
                        this.Close();
                    }
                }
                
            }
            catch
            {
                this.Close();
            }
        }
        /// <summary>
        /// 暗桩验证时间是否过期
        /// </summary>
        protected void VDT()
        {
            try
            {
                if (RegCode != "")
                {
                    string[] strs = this.GetSplitInfoFromRegCode(RegCode);
                    DateTime endDT = DateTime.Parse(this.GetInfoUnit(strs[3]));
                    if (endDT.AddDays(1) < this.GetComparedDT())
                    {
                        this.Close();
                    }
                }
            }
            catch
            {
                this.Close();
            }
        }
        /// <summary>
        /// 暗桩验证工具代号是否一致
        /// </summary>
        protected void VTC()
        {
            try
            {
                if (RegCode != "")
                {
                    string[] strs = this.GetSplitInfoFromRegCode(RegCode);
                    if (this.GetInfoUnit(strs[1]) != m_toolCode)
                    {
                        this.Close();
                    }
                }
            }
            catch
            {
                this.Close();
            }
        }
        /// <summary>
        /// 暗桩验证扩展信息
        /// </summary>
        protected void VEI()
        {
            try
            {
                if (RegCode != "")
                {
                    string[] strs = this.GetSplitInfoFromRegCode(RegCode);
                    DoValidateExtensionInfo(strs[4]);
                }
            }
            catch
            {
                this.Close();
            }
        }

        /// <summary>
        /// 处理服务端抛出的错误
        /// </summary>
        /// <param name="errMsg"></param>
        protected void HandleServerError(string errMsg)
        {
            string msg = "";
            switch (errMsg)
            {
                case "servererror":
                    msg = SERVERERROR;
                    break;
                case "expire":
                    msg = EXPIREDREGCODE;
                    break;
                case "fail":
                    msg = INVALIDREGCODE;
                    break;
                case "islatest":
                    msg = ISLATEST;
                    break;
                default:
                    msg = UNKNOWN;
                    break;
            }
            throw new RegException(Base64.Decrypt(msg));
        }

        private RegHelper() { }
        private void Test()
        {
            JWFW.BOL.BaseEntity.ConnStr = "server=localhost;uid=sa;password=password123$;database=jwgf";
            this.m_toolCode = "Test";
            Console.WriteLine(SN);
            s_VR = new ValidateReg();
            s_VR.Url = "http://localhost:10883/SVC/WS.asmx";
            this.Init();
            string ci = this.GetClientInfo();
            Console.WriteLine(m_regCode);
            Console.WriteLine(ci);
            //1.其他地方使用字符串来干扰
        }

        public const string INVALIDREGCODE = "5rOo5YbM56CB5peg5pWI77yB";        //注册码无效！
        public const string EXPIREDREGCODE = "5rOo5YbM56CB5aey6L*H5pyf77yB";    //注册码已过期！
        public const string SERVERERROR = "5pyN5Yqh5Zmo6ZSZ6K*_77yB";           //服务器错误！
        public const string ISLATEST = "5aey5pi_5pyA5pbw54mI5pys77yB";          //已是最新版本！
        public const string UNKNOWN = "5pyq55*l6ZSZ6K*_77yB";                   //未知错误！
    }
}
